package com.xm.thread;

import com.xm.thread.bean.MyRunable;
import com.xm.thread.bean.School;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class ExecutorService03 {
    public static void main(String[] args) {
        try {
            Thread thread = new Thread(() -> {
                for (int i = 0; i < 1; i++) {
                    syn("清华");
                }
            });
            Thread thread1 = new Thread(() -> {
                for (int i = 0; i < 1; i++) {
                    syn("清华");
                }
            });
            Thread thread2 = new Thread(() -> {
                syn("北大");
            });

            thread.start();
            thread1.start();
            thread2.start();
            thread.join();
            thread1.join();
            thread2.join();

            log.info("concurrentHashMap = {}", concurrentHashMap);
            log.info("atomicInt = {}", atomicInt);

            countDownLatch("11");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
        }
    }

    public static ConcurrentHashMap<String, School> concurrentHashMap = new ConcurrentHashMap<>();

    /**
     * 1、synchronized 关键字
     */
    public static void syn(String name) {
        School school = concurrentHashMap.computeIfAbsent(name, k -> new School());

        synchronized (school) {
            school.setNumber(school.getNumber() + 1);
            concurrentHashMap.put(name, school);
        }
    }

    public static ReentrantLock lock = new ReentrantLock();
    /**
     * 2、ReentrantLock
     */
    public static void reentrantLock(String name) {
        lock.lock();
        try {
            School school = concurrentHashMap.computeIfAbsent(name, k -> new School());

            school.setNumber(school.getNumber() + 1);
            concurrentHashMap.put(name, school);
        } finally {
            lock.unlock();
        }
    }

    public static volatile AtomicInteger atomicInt = new AtomicInteger();
    /**
     * 3、原子类（Atomic）
     */
    public static void atomic(String name) {
        atomicInt.incrementAndGet();
    }

    /**
     * CountDownLatch
     */
    public static void countDownLatch(String name) {
        try {
            int count = 3;
            CountDownLatch latch = new CountDownLatch(count);

            for (int i = 0; i < count; i++) {
                new Thread(() -> {
                    atomicInt.incrementAndGet();
                    latch.countDown();
                }).start();
            }
            latch.await();

            log.info("countDownLatch atomicInt = {}", atomicInt.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
        }
    }

}
